package com.bsj.power.common.def.dto.video;

import com.alibaba.fastjson.JSON;
import com.bsj.power.common.def.dto.media.UploadParam;
import com.bsj.power.common.util.DateUtils;
import com.bsj.power.common.util.ExceptionUtil;
import com.bsj.tools.Conv;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.util.BitSet;

/**
 * @Description 生成指令数据
 * @Author zhaoyang
 * @Date 2023/6/19 14:34
 */
@Slf4j
public class GenerateBodyUtil {

    /**
     * 组实时视频请求参数
     *
     * @param request
     * @return
     */
    public static byte[] generate9101(RealVideoRequest request) throws UnsupportedEncodingException {
        String host = request.getHost();
        byte[] hostByte = DataUtil.getGBKByte(host);
        int len = hostByte.length;
        Integer tcpPort = request.getTcpPort();
        Integer udpPort = request.getUdpPort();
        byte[] body = new byte[8 + len];
        int offset = 0;
        //服务器ip长度
        body[offset] = (byte) (len & 0xff);
        offset += 1;

        //服务器ip
        System.arraycopy(hostByte, 0, body, offset, len);
        offset += len;

        //tcp端口
        Conv.setShortNetOrder(body, offset, tcpPort);
        offset += 2;

        //udp端口
        Conv.setShortNetOrder(body, offset, udpPort);
        offset += 2;

        //逻辑通道号
        int channelNo = request.getChannelNo();
        body[offset] = (byte) (channelNo & 0xff);
        offset += 1;

        //数据类型
        int type = request.getDataType();
        body[offset] = (byte) (type & 0xff);
        offset += 1;

        //码流类型
        int streamType = request.getStreamType();
        body[offset] = (byte) (streamType & 0xff);
        offset += 1;
        return body;
    }

    /**
     * 录像回放请求
     *
     * @param request
     * @return
     */
    public static byte[] generate9201(BackVodRequest request) throws UnsupportedEncodingException {
        String host = request.getHost();
        byte[] hostByte = DataUtil.getGBKByte(host);
        int hostLen = hostByte.length;

        byte[] body = new byte[23 + hostLen];
        int offset = 0;

        //服务器ip长度
        body[offset] = (byte) (hostLen & 0xff);
        offset += 1;

        //服务器ip
        System.arraycopy(hostByte, 0, body, offset, hostLen);
        offset += hostLen;

        //tcp端口
        int tcpPort = request.getTcpPort();
        Conv.setShortNetOrder(body, offset, tcpPort);
        offset += 2;

        //udp端口
        int udpPort = request.getUdpPort();
        Conv.setShortNetOrder(body, offset, udpPort);
        offset += 2;

        //逻辑通道
        int channelNo = request.getChannelNo();
        body[offset] = (byte) (0xff & channelNo);
        offset += 1;

        //音视频类型
        int dateType = request.getDataType();
        body[offset] = (byte) (0xff & dateType);
        offset += 1;

        //码流类型
        int streamType = request.getStreamType();
        body[offset] = (byte) (0xff & streamType);
        offset += 1;

        //存储器类型
        int storeType = request.getStoreType();
        body[offset] = (byte) (0xff & storeType);
        offset += 1;

        //回放方式
        int backType = request.getBackType();
        body[offset] = (byte) (0xff & backType);
        offset += 1;

        //快进或快退倍速
        int speed = request.getSpeed();
        body[offset] = (byte) (0xff & speed);
        offset += 1;

        //开始时间
        String startDate = request.getStartTime();
        byte[] startByte = DateUtils.time2bcd6(startDate);
        System.arraycopy(startByte, 0, body, offset, 6);
        offset += 6;

        //结束时间
        String endDate = request.getEndTime();
        byte[] endByte = DateUtils.time2bcd6(endDate);
        System.arraycopy(endByte, 0, body, offset, 6);
        offset += 6;

        return body;
    }

    /**
     * 实时视频控制9102
     *
     * @param request
     * @return
     */
    public static byte[] generate9102(RealVideoControl request) {
        byte[] body = new byte[4];
        int offset = 0;

        //逻辑通道号
        int channelNo = request.getChannelNo();
        body[offset] = (byte) (channelNo & 0xff);
        offset += 1;

        //控制指令
        int controlType = request.getControlType();
        body[offset] = (byte) (controlType & 0xff);
        offset += 1;

        //关闭音视频类型
        int closeType = request.getCloseType();
        body[offset] = (byte) (closeType & 0xff);
        offset += 1;

        //切换码流类型
        int streamType = request.getStreamType();
        body[offset] = (byte) (streamType & 0xff);
        offset += 1;

        return body;
    }

    /**
     * 录像回放控制(关闭) 9202
     *
     * @param request
     * @return
     */
    public static byte[] generate9202(BackVodControl request) {
        byte[] body = new byte[9];
        int offset = 0;

        //逻辑通道号
        int channelNo = request.getChannelNo();
        body[offset] = (byte) (0xff & channelNo);
        offset += 1;

        //回放控制
        int controlType = request.getControlType();
        body[offset] = (byte) (0xff & controlType);
        offset += 1;

        //快进或快退倍速
        int speed = request.getSpeed();
        body[offset] = (byte) (0xff & speed);
        offset += 1;

        //拖动回放位置
        String dragTime = request.getDropTime();
        byte[] dragByte = DateUtils.time2bcd6(dragTime);
        System.arraycopy(dragByte, 0, body, offset, 6);
        offset += 6;

        return body;
    }

    /**
     * 查询终端音视频资源文件
     *
     * @param param
     * @return
     */
    public static byte[] generate9205(ResouceParam param) {
        byte[] body = new byte[24];
        int offset = 0;

        //通道
        int channelNo = param.getChannelNo() == null ? 0 : param.getChannelNo();
        body[offset] = (byte) (0xff & channelNo);
        offset += 1;

        //开始时间
        String startTime = param.getStartTime();
        byte[] sTimeByte = DateUtils.time2bcd6(startTime);
        System.arraycopy(sTimeByte, 0, body, offset, 6);
        offset += 6;

        //结束时间
        String endTime = param.getEndTime();
        byte[] eTimeByte = DateUtils.time2bcd6(endTime);
        System.arraycopy(eTimeByte, 0, body, offset, 6);
        offset += 6;

        //报警标志
        String alarmStatusStr = StringUtils.isBlank(param.getAlaramStatus()) ? "" : param.getAlaramStatus();
        long alarmStatus = set64Bit(alarmStatusStr);
        Conv.setLongNetOrder(body, offset, alarmStatus);
        offset += 8;

        //音视频资源文件类型
        int dataType = param.getDataType() == null ? 0 : param.getDataType();
        body[offset] = (byte) (dataType & 0xff);
        offset += 1;

        //码流类型
        int streamType = param.getStreamType() == null ? 0 : param.getStreamType();
        body[offset] = (byte) (streamType & 0xff);
        offset += 1;

        //存储器类型
        int storeType = param.getStoreType() == null ? 0 : param.getStoreType();
        body[offset] = (byte) (storeType & 0xff);
        offset += 1;
        return body;
    }


    /**
     * 根据传的字符添加位数(反回来设置)
     *
     * @param bits
     * @return
     */
    private static long set64Bit(String bits) {
        if (StringUtils.isBlank(bits)) {
            return 0;
        }
        String[] array = bits.split(",");
        BitSet bitSet = new BitSet(64);
        for (String bit : array) {
            bitSet.set(63 - Integer.parseInt(bit));
        }
        byte[] bytes = DataUtil.bitSet2ByteArray(bitSet);
        return Conv.getLongNetOrder(bytes, 0);
    }

    /**
     * 文件下载
     *
     * @param param
     * @param serverConfig
     * @return
     */
    public static byte[] handle9206Body(UploadParam param, FtpProperties serverConfig) {
        byte[] body = null;
        try {
            String ftpHost = serverConfig.getFtpHost();
            byte[] hostByte = DataUtil.getGBKByte(ftpHost);
            int hostLen = hostByte.length;

            String userName = serverConfig.getUserName();
            byte[] nameByte = DataUtil.getGBKByte(userName);
            int nameLen = nameByte.length;

            String password = serverConfig.getPassword();
            byte[] pwdByte = DataUtil.getGBKByte(password);
            int pwdLen = pwdByte.length;

            //todo 视具体需求组文件路径
            String path = serverConfig.getFtpPath();
            byte[] pathByte = DataUtil.getGBKByte(path);
            int pathLen = pathByte.length;

            int len = 31 + hostLen + nameLen + pwdLen + pathLen;
            //组数据
            body = new byte[len];
            int offset = 0;

            //服务器地址长度
            body[offset] = (byte) (hostLen & 0xff);
            offset += 1;

            //ftp服务地址
            System.arraycopy(hostByte, 0, body, offset, hostLen);
            offset += hostLen;

            //端口
            Conv.setShortNetOrder(body, offset, serverConfig.getFtpPort());
            offset += 2;

            //用户名长度
            body[offset] = (byte) (nameLen & 0xff);
            offset += 1;

            //用户名
            System.arraycopy(nameByte, 0, body, offset, nameLen);
            offset += nameLen;

            //密码长度
            body[offset] = (byte) (pwdLen & 0xff);
            offset += 1;

            //密码
            System.arraycopy(pwdByte, 0, body, offset, pwdLen);
            offset += pwdLen;

            //路径长度
            body[offset] = (byte) (pathLen & 0xff);
            offset += 1;

            //路径
            System.arraycopy(pathByte, 0, body, offset, pathLen);
            offset += pathLen;

            //逻辑通道号
            int channelNo = param.getChannelNo();
            body[offset] = (byte) (channelNo & 0xff);
            offset += 1;

            //开始时间
            String startTime = param.getStartTime();
            byte[] startByte = DateUtils.time2bcd6(startTime);
            System.arraycopy(startByte, 0, body, offset, 6);
            offset += 6;

            //结束时间
            String endTime = param.getEndTime();
            byte[] endByte = DateUtils.time2bcd6(endTime);
            System.arraycopy(endByte, 0, body, offset, 6);
            offset += 6;

            log.info("远程文件下载时间start:{};end:{};data={}",startTime,endTime, JSON.toJSONString(param));
            //报警标志位、
            long alarmStatus = param.getAlarmStatus() == null ? 0 : param.getAlarmStatus();
            Conv.setLongNetOrder(body, offset, alarmStatus);
            offset += 8;

            //音视频资源文件类型
            int dataType = param.getDataType() == null ? 0 : param.getDataType();
            body[offset] = (byte) (0xff & dataType);
            offset += 1;

            //码流类型
            int streamType = param.getStreamType() == null ? 0 : param.getStreamType();
            body[offset] = (byte) (0xff & streamType);
            offset += 1;

            //存储位置
            int storeType = param.getStoreType() == null ? 0 : param.getStoreType();
            body[offset] = (byte) (0xff & storeType);
            offset += 1;

            //执行任务计划
            String task = StringUtils.isBlank(param.getTask()) ? "" : param.getTask();
            int taskInt = handleSubTitle(task);
            body[offset] = (byte) (taskInt & 0xff);
            offset += 1;
        } catch (UnsupportedEncodingException e) {
            log.error("格式转换出错handle9206Body error:{}", ExceptionUtil.getStackStr(e));
        }
        return body;
    }

    /**
     * 根据传的字符添加位数(反回来设置)
     *
     * @param subtitles
     * @return
     */
    private static int handleSubTitle(String subtitles) {
        String[] array = subtitles.split(",");
        BitSet bitSet = new BitSet(32);
        for (String bit : array) {
            bitSet.set(31 - Integer.parseInt(bit));
        }
        byte[] bytes = DataUtil.bitSet2ByteArray(bitSet);
        return DataUtil.byteArrayToInt(bytes);
    }
    /**
     * 查询终端音视频资源文件9A05
     *
     * @param param
     * @return
     */
    public static byte[] generate9A05(GHResouceParam param) throws UnsupportedEncodingException {
        String host = param.getHost();
        int hostLen = host.getBytes("GBK").length;
        byte[] body = new byte[29+hostLen];
        int offset = 0;

        //ip长度
        body[offset] = (byte) (0xff & hostLen);
        offset += 1;

        //ip地址
        byte[] hostByte = host.getBytes("GBK");
        System.arraycopy(hostByte, 0, body, offset, hostLen);
        offset += hostLen;

        //tcp端口
        int tcpPort = param.getTcpPort() == null ? 0 : param.getTcpPort();
        Conv.setShortNetOrder(body, offset, tcpPort);
        offset += 2;

        //udp端口
        int udpPort = param.getUdpPort() == null ? 0 : param.getUdpPort();
        Conv.setShortNetOrder(body, offset, udpPort);
        offset += 2;

        //通道
        int channelNo = param.getChannelNo() == null ? 0 : param.getChannelNo();
        body[offset] = (byte) (0xff & channelNo);
        offset += 1;

        //开始时间
        String startTime = param.getStartTime();
        byte[] sTimeByte = DateUtils.time2bcd6(startTime);
        System.arraycopy(sTimeByte, 0, body, offset, 6);
        offset += 6;

        //结束时间
        String endTime = param.getEndTime();
        byte[] eTimeByte = DateUtils.time2bcd6(endTime);
        System.arraycopy(eTimeByte, 0, body, offset, 6);
        offset += 6;

        //报警标志
        String alarmStatusStr = StringUtils.isBlank(param.getAlaramStatus()) ? "" : param.getAlaramStatus();
        long alarmStatus = set64Bit(alarmStatusStr);
        Conv.setLongNetOrder(body, offset, alarmStatus);
        offset += 8;

        //音视频资源文件类型
        int dataType = param.getDataType() == null ? 0 : param.getDataType();
        body[offset] = (byte) (dataType & 0xff);
        offset += 1;

        //码流类型
        int streamType = param.getStreamType() == null ? 0 : param.getStreamType();
        body[offset] = (byte) (streamType & 0xff);
        offset += 1;

        //存储器类型
        int storeType = param.getStoreType() == null ? 0 : param.getStoreType();
        body[offset] = (byte) (storeType & 0xff);
        offset += 1;
        return body;
    }

}
